#!/usr/bin/python3


import requests
import getopt
import sys
import json
import time
import uuid
import os
import subprocess
import signal
import importlib
import re



def usage():
	print(
	"""
	Usage: %s [option]
	-u or --user:      login user name, must be email address, it's must be specify login user and it's cann't NULL
	-p or --password:  login password, it's must be specify password and it's cann't NULL

	-e or --email:     message  sender's email
	-m or --message:   specify message, python %s -s username -m "hello word"
	-c or --cmd:       specify shell cmd 

	-x or --extern:    import extern config file 

	-h or --help:      show help
	"""%(sys.argv[0], sys.argv[0])
	)


#send msg
def send_msg(conversation_id, token_id, ticket_id, message ):
	url = "https://fleep.io/api/message/send/"+conversation_id 
	#print(url)

	r = requests.post( url ,  cookies={"token_id": token_id }, json={ "ticket": ticket_id  , "message": message.__str__()  })
	#print(r.status_code)
	#print(r.json())

#login
def login( user_name , password ):
	url = 'https://fleep.io/api/account/login'
	login_dict   = {"email": user_name, "password":password}
	r = requests.post( url , json=login_dict)
	if(r.status_code != 200):
		#print("[ERROR]: login failed %d!"%(r.status_code))
		return (False , '' , '' , '')

	resp       = r.json()

	ticket     = resp["ticket"]
	account_id = resp["account_id"]
	token_id   = r.cookies["token_id"]

	#print("ticket  : %s\ntoken_id: %s\naccount_id:%s"%(ticket, token_id, account_id))
	return (True , account_id , token_id , ticket)

# logout
def logout(token_id , ticket):
	r = requests.post("https://fleep.io/api/account/logout",  cookies={"token_id":  token_id }, json={"ticket": ticket })


# get  last  event_horizon
def GetLastEvent(token_id , ticket):
	url = "https://fleep.io/api/account/sync"
	r = requests.post(url ,  cookies={"token_id": token_id }, json={ "ticket": ticket })

	if(r.status_code != 200):
		return (False , -1 )

	resp           = r.json()
	last_event     = resp['event_horizon']

	#print('last event:' , last_event)
	return (True , last_event )


# get contacts
def GetContacts(token_id , ticket):
	url = "https://fleep.io/api/contact/sync/all"
	cs = {}
	# get all contact
	r     = requests.post(url ,  cookies={"token_id": token_id }, json={"ticket": ticket })
	if(r.status_code != 200):
		return (False , {} )

	resp  = r.json()
	for c in  resp['contacts']:
		cs[c['account_id']] = c['email']

	return (True , cs)

#  receive event
def ReceiveEvent(token_id , ticket , last_event = 0):
	url = "https://fleep.io/api/account/poll"
	r = requests.post(url ,  cookies={"token_id": token_id }, json={ "ticket": ticket  , "wait": True, "event_horizon": last_event  })
	if(r.status_code != 200):
		return (False , {} )

	resp = r.json()
	return (True , resp)


#  add  command
def add_command(email , msg , cmd):
	if email not in commands.keys():
		commands[email] = []

	commands[email].append((msg,cmd,))


def ProcessArgv():
	global user_name,password,sender_email,s_message,s_cmd,s_extern

	try:
		opts, args = getopt.getopt(sys.argv[1:], "u:p:e:m:c:x:h", ["user", "password",'email','message','cmd','extern'])

	except getopt.GetoptError:
		print("[ERROR]: argv error!")
		return False


	for cmd, arg in opts:
		if cmd in ("-h", "--help"):
			usage()
			sys.exit()
		elif cmd in ("-u", "--user"):
			user_name = arg	
		elif cmd in ("-p", "--password"):
			password = arg
		elif cmd in ("-e", "--email"):
			sender_email = arg	
		elif cmd in ("-m", "--message"):
			s_message = arg	
		elif cmd in ("-c", "--cmd"):
			s_cmd = arg	
		elif cmd in ("-x", "--extern"):
			s_extern = arg	



user_name         = ""
password          = ""
sender_email      = ""
s_message         = ""
s_cmd             = ""
s_extern          = ""

commands = {}

ProcessArgv()


if  (sender_email !='') and (s_message != '') and (s_cmd != '') :
	add_command(sender_email , s_message , s_cmd)

if  s_extern != '':
	config = importlib.import_module(s_extern)
	if 'command_list' in dir(config):
		for c in config.command_list:
			add_command(c[0],c[1],c[2])

	if 'password' in dir(config) :
		password = config.password

	if 'username' in dir(config) :
		user_name = config.username


if( user_name == "" or password == "" ):
	print("[ERROR]: must be specify user and password or a config file!")
	sys.exit()


ret , account_id  ,  token_id , ticket = login(user_name , password)

if not ret:
	print("login failed" , user_name)
	sys.exit(-1)

print("ticket  : %s\ntoken_id: %s\naccount_id:%s"%(ticket, token_id, account_id))


ret , last_event = GetLastEvent(token_id , ticket)

if not ret:
	print("get last event failed")
	sys.exit(-2)

print('last event:' , last_event)


ret , contacts = GetContacts(token_id , ticket)
if not ret:
	print("get contacts failed")
	sys.exit(-3)



def term_sig_handler(signum, frame):
	print('catched singal: %d' % signum)
	print('logout')
	logout(token_id , ticket)
	sys.exit()

signal.signal(signal.SIGTERM, term_sig_handler)   #kill pid
signal.signal(signal.SIGINT, term_sig_handler)     #ctrl -c



# word spliter
spliter = re.compile(r'\w+')



# reci new msg
while True:
	print('last event' , last_event)
	ret , resp = ReceiveEvent(token_id , ticket , last_event)
	if not ret :
		continue

	last_event = resp["event_horizon"]

	for  e in resp['stream']:
		if 'mk_message_type' not in e.keys():
			#print('not message')
			continue

		#print('find msg')

		if e['mk_message_type'] != 'text':
			#print('not txt')
			continue
		msg              = e['message']
		sender 	         = e['account_id']
		conversation_id  = e['conversation_id']

		#print('find txt')
		#print(e)

		if sender not in  contacts.keys():
			#print('not allow sender')
			continue

		sender_email = contacts[sender]

		if sender_email not in commands.keys():
			continue


		ws = spliter.findall(msg.lower())

		for  m_c in commands[sender_email]:
			# print( "check " ,msg , m_c[0] , m_c[1])

			if m_c[0].lower() not in ws :
				continue

			#print('find keyword')

			print('start ' , m_c[1])

			sh_r = subprocess.Popen( m_c[1]  , shell=True , stdout = subprocess.PIPE)
			sh_r.poll()
			print('exec ok')
			msg_r = sh_r.stdout.readlines()
			print('get stdout ok')
			m = ""
			for l in msg_r:
				l = l.decode().strip().strip('\r').strip('\n')
				m = m + l.__str__() + '\r\n'

			#print(m)

			send_msg(conversation_id, token_id, ticket  ,  m )



